/*********************************************************
*Copyright (c) 2015 zhongsx. All Rights in Pw 
*@des: B型事件处理队列 
* 使用生产者多消费者模型
*@name: BMsgQueue.cpp
*@author: zhongsx
*@time: 2015-02-05
*********************************************************/

#include "BMsgQueue.h"

boost::unordered_map<int, boost::shared_ptr<BMsgQueue>> BMsgQueue::QueueMap; //全局容器
boost::mutex	BMsgQueue::queue_mutex; //全局锁

BMsgQueue::BMsgQueue()
{
	_queue = boost::circular_buffer<CallBackNode>(MSGQUEUE_SIZE);
}

BMsgQueue::~BMsgQueue()
{

}

boost::shared_ptr<BMsgQueue> BMsgQueue::GetMsgQueue(int _type){
	boost::mutex::scoped_lock lock(BMsgQueue::queue_mutex);
	if (QueueMap.count(_type) == 0){
		boost::shared_ptr<BMsgQueue> ptr( new BMsgQueue() );
		QueueMap[_type] = ptr;
	}
	return QueueMap[_type];
}

void BMsgQueue::DestroyInstance(int _type){
	if (QueueMap.count(_type) == 0){
		return;
	}
	QueueMap.erase(_type);
}


//
bool BMsgQueue::empty() const {
	boost::mutex::scoped_lock lock(_mutex); 
	return _queue.empty();
}

int BMsgQueue::size() const {
	boost::mutex::scoped_lock lock(_mutex); 
	return _queue.size();
}

//wait size量 
int BMsgQueue::push_wait_queue(boost::shared_ptr<BMsgQueue> msgq, int size){
	boost::mutex::scoped_lock lock(_mutex); 
	int num = _queue.size();
	while(num == 0){
		_variable.wait(lock);
		num = _queue.size();
	}
	num = size < num ? size : num;
	T_list rlist = get_node_list(num);
	msgq->push_list(rlist);
	return num;
}

//size量
void  BMsgQueue::push_list(T_list& list){
	boost::mutex::scoped_lock lock(_mutex); 

	while(list.size() > 0)
	{
		CallBackNode node = list.front();
		list.pop_front();
		_queue.push_back(node);
	}

	lock.unlock();
	_variable.notify_all();  
}

//push 1 个
void BMsgQueue::push_back(CallBackNode node){
	boost::mutex::scoped_lock lock(_mutex); 
	_queue.push_back(node);
	lock.unlock();
	_variable.notify_all();
}

CallBackNode BMsgQueue::get_front()
{
	boost::mutex::scoped_lock lock(_mutex); 
	if (_queue.size() == 0)
	{
		return NULL;
	}
	CallBackNode node = _queue.front();
	_queue.pop_front();
	return node;
}

T_list BMsgQueue::get_node_list(int size)
{
	T_list _list;
	int num = _queue.size();
	num = size < num ? size : num;
	for(int i = 0; i < num; i++){
		CallBackNode node = _queue.front();
		_list.push_back(node);
		_queue.pop_front();
	}
	return _list;
}